S3にあるparquetファイルのメタデータのみにアクセスしてスキーマ情報を取得する
データアナリティクス事業本部のueharaです。
今回は、S3にあるparquetファイルのメタデータのみにアクセスしてスキーマ情報を取得してみたいと思います。
はじめに
S3にデータ容量の大きなparquetファイルがあり、例えばLambda内でそのparquetファイルのスキーマ情報を取得したい際にデータを丸ごとLambdaに持ってくるのは不都合な場合があります。
そこで、S3にあるparquetファイルのメタデータのみにアクセスしてスキーマ情報を取得してみたいと思います。
parquetファイルの構造
parquet-formatを見ると、parquetファイルの構造は以下のようになっております。
(参考)
これを見ると、Footer情報にメタデータが存在し、実際のFooter情報の長さは最後の8バイトの内前半の4バイトに保存されており、後半の4バイトは PAR1
というマジックナンバーとなっていることが分かります。
なお、Footer情報の長さはリトルエンディアンのようです。
boto3ではバイトレンジを指定してS3にあるオブジェクトのデータを取得することができるので、それを活用してメタデータのみ取得したいと思います。
やってみた
今回、テストに利用するparquetファイルはSample Parquet datasets for downloadの Weather.parquet
にします。
作成したPythonスクリプトは以下の通りです。
import io import boto3 from pyarrow import parquet # S3オブジェクトの情報を設定 s3_bucket_name = "cm-da-uehara" s3_key = "tmp/Weather.parquet" # S3クライアントの初期化 s3 = boto3.client("s3") # ファイルの最後の8バイトを取得して、フッタの長さを取得 last_bytes = s3.get_object(Bucket=s3_bucket_name, Key=s3_key, Range="bytes=-8")[ "Body" ].read() footer_length = int.from_bytes(last_bytes[:4], "little") magic = last_bytes[4:] # 想定する構造になっているか確認 assert magic == b"PAR1", "Invalid parquet file" # フッタの長さを使用して実際のフッタ情報を取得 footer_range = f"bytes=-{footer_length + 8}-" footer_bytes = s3.get_object(Bucket=s3_bucket_name, Key=s3_key, Range=footer_range)[ "Body" ].read() # フッタ情報のBytesIOオブジェクトを作成 footer_stream = io.BytesIO(footer_bytes) # メタデータの取得 parquet_metadata = parquet.read_metadata(footer_stream) schema = parquet_metadata.schema.to_arrow_schema() # カラム名とデータ型の表示 for field in schema: print(f"{field.name}: {field.type}")
各処理でやっていることはコメントに記載している通りです。
上記スクリプトを実行すると、結果は以下の通りでした。
$ python test.py MinTemp: double MaxTemp: double Rainfall: double Evaporation: double Sunshine: string WindGustDir: string WindGustSpeed: string WindDir9am: string WindDir3pm: string WindSpeed9am: string WindSpeed3pm: int64 Humidity9am: int64 Humidity3pm: int64 Pressure9am: double Pressure3pm: double Cloud9am: int64 Cloud3pm: int64 Temp9am: double Temp3pm: double RainToday: string RISK_MM: double RainTomorrow: string
きちんとスキーマ情報が取得できていることが分かります。
最後に
今回は、S3にあるparquetファイルのメタデータのみにアクセスしてスキーマ情報を取得してみました。
参考になりましたら幸いです。